scrolledwindow: Be smarter at invalidating overshoot areas
authorCarlos Garnacho <carlosg@gnome.org>
Sun, 27 Jul 2014 11:39:51 +0000 (13:39 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Thu, 28 Aug 2014 14:44:12 +0000 (16:44 +0200)
The previous way to invalidate was meant to work on the overshoot window
so it wouldn't be as taxing. Since the overshoot window is gone, this
would invalidate way more than intended. So constrain invalidated areas
to the sides where overshoot is happenning at that moment.

https://bugzilla.gnome.org/show_bug.cgi?id=735223

gtk/gtkscrolledwindow.c

index fd090cb0d0c96bc45da21b6c5b2d50fdc171154d..79f8cd8dddefbfaed251bc2f554e01b55689ab9a 100644 (file)
@@ -600,6 +600,53 @@ scrolled_window_drag_begin_cb (GtkScrolledWindow *scrolled_window,
   gtk_gesture_set_sequence_state (gesture, sequence, state);
 }
 
+static void
+gtk_scrolled_window_invalidate_overshoot (GtkScrolledWindow *scrolled_window)
+{
+  GtkAllocation child_allocation, allocation;
+  gint overshoot_x, overshoot_y;
+  GdkRectangle rect;
+
+  if (!_gtk_scrolled_window_get_overshoot (scrolled_window, &overshoot_x, &overshoot_y))
+    return;
+
+  gtk_widget_get_allocation (GTK_WIDGET (scrolled_window), &allocation);
+  gtk_scrolled_window_relative_allocation (GTK_WIDGET (scrolled_window),
+                                           &child_allocation);
+  child_allocation.x += allocation.x;
+  child_allocation.y += allocation.y;
+
+  if (overshoot_x != 0)
+    {
+      if (overshoot_x < 0)
+        rect.x = child_allocation.x;
+      else
+        rect.x = child_allocation.x + child_allocation.width - MAX_OVERSHOOT_DISTANCE;
+
+      rect.y = child_allocation.y;
+      rect.width = MAX_OVERSHOOT_DISTANCE;
+      rect.height = child_allocation.height;
+
+      gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET (scrolled_window)),
+                                  &rect, TRUE);
+    }
+
+  if (overshoot_y != 0)
+    {
+      if (overshoot_y < 0)
+        rect.y = child_allocation.y;
+      else
+        rect.y = child_allocation.y + child_allocation.height - MAX_OVERSHOOT_DISTANCE;
+
+      rect.x = child_allocation.x;
+      rect.width = child_allocation.width;
+      rect.height = MAX_OVERSHOOT_DISTANCE;
+
+      gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET (scrolled_window)),
+                                  &rect, TRUE);
+    }
+}
+
 static void
 scrolled_window_drag_update_cb (GtkScrolledWindow *scrolled_window,
                                 gdouble            offset_x,
@@ -611,6 +658,8 @@ scrolled_window_drag_update_cb (GtkScrolledWindow *scrolled_window,
   GtkAdjustment *vadjustment;
   gdouble dx, dy;
 
+  gtk_scrolled_window_invalidate_overshoot (scrolled_window);
+
   if (!priv->capture_button_press)
     {
       GdkEventSequence *sequence;
@@ -636,8 +685,7 @@ scrolled_window_drag_update_cb (GtkScrolledWindow *scrolled_window,
                                                  dy, TRUE, FALSE);
     }
 
-  gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET (scrolled_window)),
-                              NULL, FALSE);
+  gtk_scrolled_window_invalidate_overshoot (scrolled_window);
 }
 
 static void
@@ -2501,6 +2549,8 @@ scrolled_window_deceleration_cb (GtkWidget         *widget,
   hadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->hscrollbar));
   vadjustment = gtk_range_get_adjustment (GTK_RANGE (priv->vscrollbar));
 
+  gtk_scrolled_window_invalidate_overshoot (scrolled_window);
+
   if (data->hscrolling &&
       gtk_kinetic_scrolling_tick (data->hscrolling, elapsed, &position))
     {
@@ -2525,7 +2575,7 @@ scrolled_window_deceleration_cb (GtkWidget         *widget,
       return G_SOURCE_REMOVE;
     }
 
-  gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE);
+  gtk_scrolled_window_invalidate_overshoot (scrolled_window);
 
   return G_SOURCE_CONTINUE;
 }